import { Inject, Injectable } from '@nestjs/common';
import * as Sequelize from 'sequelize';
import { Bill } from './bill.model';
import { BillQueryDto } from './dto/bill-query.dto';
import { CreateBillDto } from './dto/create-bill.dto';
import dayjs = require('dayjs');
import sequelize from '../sequelize';
import { Logger } from 'src/utils/log4js';

@Injectable()
export class BillService {
  constructor(
    @Inject('BillRepository')
    private readonly billRepository: typeof Bill,
  ) {}

  async findAll(query: BillQueryDto, user) {
    // eslint-disable-next-line prefer-const
    let { pageNo, pageSize, billDate, category } = query;
    pageNo = Number(query.pageNo || 1);
    pageSize = Number(query.pageSize || 10);
    const where = {};
    where['user_id'] = user.id;

    const dayResult = await this.list(
      user.id,
      category,
      billDate,
      pageNo,
      pageSize,
    );
    const dayList = JSON.parse(JSON.stringify(dayResult));
    const dataList = [];
    if (dayList.length > 0) {
      for (let i = 0; i < dayList.length; i++) {
        const day = dayList[i].day;
        const day_pay = dayList[i].day_pay;
        const day_income = dayList[i].day_income;
        const billData = await this.listByDay(user.id, category, day);
        const billList = JSON.parse(JSON.stringify(billData));
        dataList.push({
          day,
          day_pay: day_pay / 100,
          day_income: day_income / 100,
          week: dayjs(day).day() + 1,
          bills: billList,
        });
      }
    }
    const allData = await this.allList(user.id, category, billDate);
    const allList = JSON.parse(JSON.stringify(allData));
    // 当月总支出：支付类型：支出: pay，收入: income
    const totalExpense =
      allList.reduce((curr, next) => {
        if (next.flag === 'pay') {
          curr += Number(next.cost);
          return curr;
        }
        return curr;
      }, 0) / 100;
    const totalIncome =
      allList.reduce((curr, next) => {
        if (next.flag === 'income') {
          curr += Number(next.cost);
          return curr;
        }
        return curr;
      }, 0) / 100;

    // 天数去重
    const newAllList = [];
    allList.forEach((item) => {
      if (!newAllList.find((i) => i.record_time === item.record_time)) {
        newAllList.push(item);
      }
    });
    const total = newAllList.length;
    Logger.info(
      '总条数：',
      total,
      '当月总支出：',
      totalExpense,
      '当月总收入：',
      totalIncome,
    );
    return {
      data: {
        totalExpense,
        totalIncome,
        list: dataList,
        total,
        pageSize,
        pageNo,
      },
    };
  }

  async add(body: CreateBillDto, user: any) {
    const data: any = { ...body };
    const record_time = dayjs(data.record_time).format('YYYY-MM-DD');
    data.week = dayjs(record_time).day() + 1;
    data.year = dayjs(record_time).year();
    data.month = dayjs(record_time).month() + 1;
    data.day = dayjs(record_time).date();
    data.user_id = user.id;
    data.create_time = dayjs().format('YYYY-MM-DD HH:mm:ss');
    data.update_time = dayjs().format('YYYY-MM-DD HH:mm:ss');
    data.cost = Number(data.cost) * 100;
    const bill = await this.billRepository.create(data);
    await bill.save();
    return { msg: '账单添加成功' };
  }

  async update(id: number, body: CreateBillDto) {
    const data: any = { ...body };
    const record_time = dayjs(data.record_time).format('YYYY-MM-DD');
    data.week = dayjs(record_time).day() + 1;
    data.year = dayjs(record_time).year();
    data.month = dayjs(record_time).month() + 1;
    data.day = dayjs(record_time).date();
    data.cost = Number(data.cost);
    data.update_time = dayjs().format('YYYY-MM-DD HH:mm:ss');
    const bill = await this.billRepository.findByPk(id);
    if (bill) {
      await bill.update(data);
      return { msg: '账单修改成功' };
    }
    return { code: -1, msg: '账单不存在' };
  }

  async delete(id: number, user: any) {
    const bill = await this.billRepository.findByPk(id);
    if (bill) {
      if (user.id === bill.user_id) {
        await bill.destroy();
        return { msg: '账单删除成功' };
      } else {
        return { code: -1, msg: '非本人账单无法删除' };
      }
    }
    return { code: -1, msg: '账单不存在' };
  }

  async analyze(query: any, user: any) {
    const { billDate } = query;
    if (!billDate) {
      return { code: -1, msg: '日期不能为空' };
    }
    const monthBillResult = await this.monthBill(billDate, user.id);
    const monthBillList = JSON.parse(JSON.stringify(monthBillResult));
    const dataList = monthBillList.reduce((curr, next) => {
      const index = curr.findIndex(
        (item) => item.category_id === next.category_id,
      );
      if (index === -1) {
        curr.push({
          category_id: next.category_id,
          name: next.category_name,
          flag: next.flag === 'pay' ? '支出' : '收入',
          value: next.cost / 100,
        });
      }
      if (index > -1) {
        curr[index].cost += next.cost;
      }
      return curr;
    }, []);
    const payList = dataList.filter((item) => item.flag === '支出');
    const incomeList = dataList.filter((item) => item.flag === '收入');
    // 当月总支出：支付类型：支出: pay，收入: income
    const totalExpense =
      monthBillList.reduce((curr, next) => {
        if (next.flag === 'pay') {
          curr += Number(next.cost);
          return curr;
        }
        return curr;
      }, 0) / 100;
    const totalIncome =
      monthBillList.reduce((curr, next) => {
        if (next.flag === 'income') {
          curr += Number(next.cost);
          return curr;
        }
        return curr;
      }, 0) / 100;
    Logger.info('当月总支出：', totalExpense, '当月总收入：', totalIncome);
    return {
      data: {
        totalExpense,
        totalIncome,
        // list: dataList,
        payList,
        incomeList,
      },
    };
  }

  // 获取账单天数列表
  async list(user_id, category, billDate, pageNo, pageSize) {
    try {
      const category_str = category ? ` and t.category_id = ${category}` : '';
      const billDate_str = billDate
        ? ` and DATE_FORMAT(t.record_time,'%Y-%m') = '${billDate}'`
        : '';
      const sql = `SELECT STR_TO_DATE(t.record_time, '%Y-%m-%d') day, SUM(case when t.flag = 'pay' then t.cost else 0 end) day_pay, SUM(case when t.flag = 'income' then t.cost else 0 end) day_income FROM t_bill t WHERE user_id = ${user_id} ${category_str} ${billDate_str}  GROUP BY record_time desc limit ${
        (pageNo - 1) * pageSize
      },${pageSize}`;
      const result = await sequelize.query(sql, {
        type: Sequelize.QueryTypes.SELECT, // 查询方式
      });
      return result;
    } catch (err) {
      Logger.error(err);
    }
  }

  // 获取某一天账单列表
  async listByDay(user_id, category, billDate) {
    try {
      const year = dayjs(billDate).year();
      const month = dayjs(billDate).month() + 1;
      const day = dayjs(billDate).date();
      const category_str = category ? ` and category_id = ${category}` : '';
      const billDate_str = ` and month = ${month} and day = ${day} and year = ${year}`;
      const sql = `SELECT a.*, b.name as category_name, b.icon FROM t_bill a, t_category b WHERE a.category_id = b.id and user_id = ${user_id} ${category_str} ${billDate_str} ORDER BY record_time DESC`;
      const result = await sequelize.query(sql, {
        type: Sequelize.QueryTypes.SELECT, // 查询方式
      });
      return result;
    } catch (err) {
      Logger.error(err);
    }
  }

  // 获取所有账单数据
  async allList(user_id, category, billDate) {
    try {
      const year = dayjs(billDate).year();
      const month = dayjs(billDate).month() + 1;
      const category_str = category ? ` and category_id = ${category}` : '';
      const billDate_str = ` and month = ${month} and year = ${year}`;
      const sql = `SELECT * FROM t_bill WHERE user_id = ${user_id} ${category_str} ${billDate_str}`;
      const result = await sequelize.query(sql, {
        type: Sequelize.QueryTypes.SELECT, // 查询方式
      });
      return result;
    } catch (err) {
      Logger.error(err);
    }
  }

  // 获取月份账单统计数据
  async monthBill(billDate, user_id) {
    try {
      const year = dayjs(billDate).year();
      const month = dayjs(billDate).month() + 1;
      const billDate_str = ` and month = ${month} and year = ${year}`;
      const sql = `SELECT a.*, b.name as category_name FROM t_bill a, t_category b WHERE a.category_id = b.id and user_id = ${user_id}  ${billDate_str}`;
      const result = await sequelize.query(sql, {
        type: Sequelize.QueryTypes.SELECT, // 查询方式
      });
      return result;
    } catch (err) {
      Logger.error(err);
    }
  }
}
